//author Sylvain Bertrand <digital.ragnarok@gmail.com>
//Protected by GNU Affero GPL v3 with some exceptions.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>
#include <error.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

#include <linux/types.h>

#include <alga/pixel_fmts.h>
#include <alga/amd/dce6/dce6.h>
#include <alga/amd/si/ioctl.h>

#define e(m,...) error(0,0,m,##__VA_ARGS__)
#define o(m,...) printf(m "\n",##__VA_ARGS__)
#define unsignedl unsigned long
#define unsignedll unsigned long long

int main(int argc, char *argv[])
{
  if(argc<3){
    e("missing arguments");
    return EXIT_FAILURE;
  }

  errno=0;
  int f=open("/dev/si0", O_RDWR);
  if(f==-1){
    e("open failed:%s",strerror(errno));
    return EXIT_FAILURE;
  }

  struct si_dma dma;
  struct si_dma_u32_fill *u32_fill=&dma.params.u32_fill;
  struct si_timeouts_info *t_info=&dma.t_info;
  dma.type=SI_DMA_TYPE_U32_FILL;
  dma.dir=SI_DMA_ON_DEVICE;
  //we don't really care here lets put one seconde!
  t_info->ring.n_max=1;
  t_info->ring.us=1000000;
  t_info->fence.n_max=1;
  t_info->fence.us=1000000;
  u32_fill->dst_addr=strtoul(argv[1],NULL,16);
  u32_fill->dws_n=strtoul(argv[2],NULL,16);
  u32_fill->constant=strtoul(argv[3],NULL,16);
  unsignedl req=_IOW('d',SI_DMA,dma);
  errno=0;
  int r=ioctl(f,req,&dma);
  switch(r){
  case -1:
    e("dma fill failed:%s",strerror(errno));
    return EXIT_FAILURE;
  case SI_RING_TIMEOUT:
    e("dma fill failed:ring timeout");
    return EXIT_FAILURE;
  case SI_FENCE_TIMEOUT:
    e("dma fill failed:fence timeout");
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
